# -*- coding: utf-8 -*-
import json
import os
import sys
import copy

import numpy as np
from PySide2.QtCore import Qt, Signal, QThread, QRegExp, QModelIndex, QRegularExpression
from PySide2.QtWidgets import QMessageBox, QApplication, QTableWidgetItem, QStyledItemDelegate, QLineEdit, QTableWidget, \
    QItemDelegate, QVBoxLayout, QLabel, QDialog, QSizePolicy, QWidget, QStyleOptionButton, QStyle
from PySide2.QtGui import QDoubleValidator, QValidator, QRegExpValidator, QIntValidator, QFont, QTextCharFormat, QColor, \
    QTextCursor, QPainter, QLinearGradient, QBrush, QPixmap, QRegularExpressionValidator
from datetime import datetime

from src.word_template_filler import fill_template
from src.algorithm import AnchorDesign

try:
    from src.controller.main_controller import MainController
except Exception as e:
    pass

import inspect


def get_init_parameter_names(cls):
    """获取类 __init__ 方法的参数名列表（跳过 self 参数）"""
    # 获取 __init__ 方法
    init_method = cls.__init__

    # 获取方法签名
    try:
        sig = inspect.signature(init_method)
    except ValueError:  # 处理内置方法等特殊情况
        return []

    # 提取参数名并过滤掉 'self'
    parameters = [
        param.name
        for param in sig.parameters.values()
        if param.name != 'self'
    ]
    return parameters


def set_tables_header_align(self, tables: list, align: Qt.Alignment):
    for table in tables:
        for i in range(table.columnCount()):
            # 获取表头项
            header_item = table.horizontalHeaderItem(i)
            if header_item is not None:
                header_item.setTextAlignment(align)


def show_error_message(parent, title='文件格式错误', message='所选文件不是符合规范的项目文件',
                       detail='请选择JSON格式的文件 (*.json)'):
    """显示错误提示框"""
    msg_box = QMessageBox(parent)
    msg_box.setIcon(QMessageBox.Critical)
    msg_box.setWindowTitle(title)
    msg_box.setText(message)
    msg_box.setInformativeText(detail)
    msg_box.setStandardButtons(QMessageBox.Ok)
    msg_box.exec_()


def resource_path(relative_path):
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    relative_path = os.path.normpath(relative_path)
    return os.path.join(base_path, relative_path)


def get_current_directory():
    """
    获取当前程序运行的目录，支持打包为EXE后的环境
    """
    # 获取当前执行文件的路径
    if getattr(sys, 'frozen', False):
        # 当程序被打包为EXE时
        # sys.executable指向打包后的EXE文件路径
        current_path = os.path.dirname(sys.executable)
    else:
        # 开发环境中，__file__指向当前脚本文件
        current_path = os.path.dirname(os.path.abspath(__file__))

    # 规范化路径（处理斜杠/反斜杠问题）
    current_path = os.path.normpath(current_path)
    print(current_path)
    return current_path


def set_window_size_by_resolution(parent, x=1554, y=1015, geometry_ratio=0.6):
    """根据屏幕分辨率设置窗口大小和比例"""
    # 获取主屏幕信息
    screen = QApplication.primaryScreen()
    screen_geometry = screen.geometry()

    # 目标长宽比 (4:3)
    target_ratio = 1554 / 1015

    # 计算适合屏幕的窗口大小
    # 窗口宽度取屏幕宽度的80%
    window_width = int(screen_geometry.width() * geometry_ratio)

    # 根据长宽比计算窗口高度
    window_height = int(window_width / target_ratio)

    # 确保窗口高度不超过屏幕高度的85%
    if window_height > screen_geometry.height() * 0.85:
        window_height = int(screen_geometry.height() * 0.85)
        window_width = int(window_height * target_ratio)

    # 设置窗口大小和位置
    parent.setGeometry(
        (screen_geometry.width() - window_width) // 2,  # x
        (screen_geometry.height() - window_height) // 2,  # y
        window_width,  # width
        window_height  # height
    )


def get_table_all_values(table):
    """获取所有表格的值"""
    all_data = []

    # 遍历所有行和列
    for row in range(table.rowCount()):
        row_data = []
        for col in range(table.columnCount()):
            item = table.item(row, col)
            # 如果单元格为空，item会是None
            value = item.text() if item else ""
            row_data.append(value)
        all_data.append(row_data)
    # 构建显示信息
    message = f"表格{table.objectName()}中的所有数据：\n\n"
    for i, row_data in enumerate(all_data):
        message += f"第 {i + 1} 行: {', '.join(row_data)}\n"
    print(message)

    return all_data


def validator_table(table, begin_num=0, end_num=1000, decimals=2):
    # 为所有单元格设置浮点数验证器
    for row in range(table.rowCount()):
        for col in range(table.columnCount()):
            item = QTableWidgetItem()
            validator = QDoubleValidator(begin_num, end_num, decimals)
            item.setValidator(validator)
            table.setItem(row, col, item)


def set_cell_non_editable(tb, row, col, color=QColor(240, 240, 240)):
    """设置单元格不可编辑并设置背景色"""
    item = tb.item(row, col)
    if item:
        # 移除可编辑属性
        item.setFlags(item.flags() & ~Qt.ItemIsEditable)
        # 设置背景色
        item.setBackground(color)
    else:
        # 如果单元格不存在，则创建一个新的
        item = QTableWidgetItem()
        item.setFlags(item.flags() & ~Qt.ItemIsEditable)
        item.setBackground(color)
        tb.setItem(row, col, item)


def round_to_two_decimal(num):
    """
    将输入的数字（float或数字字符串）四舍五入保留2位小数

    参数:
        num: 可以是float类型或表示数字的字符串

    返回:
        float: 四舍五入后保留2位小数的结果

    异常:
        ValueError: 当输入不是有效的数字或数字字符串时抛出
    """
    try:
        # 将输入转换为float类型
        float_num = float(num)
        # 四舍五入保留2位小数
        rounded_num = round(float_num, 2)
        return rounded_num
    except ValueError:
        return num


class NumericDelegate(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = super().createEditor(parent, option, index)

        regex = QRegExp(r"^(\d*\.?\d{0,2}|\d+\.?)$")  # 允许数字、小数点后最多两位、空值
        validator = QRegExpValidator(regex)
        # validator = QDoubleValidator()
        # validator.setRange(0.0, 100000)  # 设置范围
        # validator.setDecimals(2)  # 小数点位数
        editor.setValidator(validator)
        return editor




class SaveFileThread(QThread):
    update_signal = Signal(object)

    def __init__(self, path, data, main_window=None):
        super(SaveFileThread, self).__init__()
        self.jsondata = data
        self.path = path
        self.main_window = main_window

    def run(self):
        res = {
            "status": "",
            "message": ""
        }
        try:
            if self.path is None:
                res['status'] = -3
                res['message'] = ''
                self.update_signal.emit(res)
                # QApplication.instance().quit()
                return
            if self.main_window is not None:
                save_data = {}
                for widget in self.main_window.findChildren(QTableWidget):
                    # print(widget.objectName())
                    # get_table_all_values(widget)
                    save_data[widget.objectName()] = get_table_all_values(widget)
                with open(self.path, 'w+', encoding='utf-8') as f:
                    f.write(json.dumps(save_data, indent=4, ensure_ascii=True))
            else:
                with open(self.path, 'w+', encoding='utf-8') as f:
                    f.write(json.dumps(self.jsondata))
            res['status'] = 1
            res['message'] = '保存成功'
            self.update_signal.emit(res)  # 发送信号，传递数据
        except PermissionError as e:
            res['status'] = -1
            res['message'] = '文件权限不足，请检查文件是否被其他程序占用或是否有写入权限'
            self.update_signal.emit(res)
        except Exception as e:
            res['status'] = -2
            res['message'] = f'保存失败: {str(e)}'
            self.update_signal.emit(res)


class OutWordThread(QThread):
    update_signal = Signal(object)

    def __init__(self, main_window: "MainController" = None, algo_class=None):
        super(OutWordThread, self).__init__()
        self.main_window = main_window
        self.algo_class = algo_class

    def run(self):
        global output_path
        gener_res = {
            "status": "",
            "message": ""
        }
        try:
            # 拉压扩大
            if self.main_window.img_index == 0:
                docx_data = {}
                if validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_soil, spec_row_count=1):
                    tableWidget_laya_kuoda_soil = get_table_all_values(self.main_window.tableWidget_laya_kuoda_soil)
                    for i, v in enumerate(tableWidget_laya_kuoda_soil):
                        if i > 5:
                            print('目前只取前6行')
                            break
                        docx_data[f'name{i}'] = v[1]
                        docx_data[f'zd{i}'] = v[2]
                        docx_data[f'njl{i}'] = v[3]
                        docx_data[f'nmcj{i}'] = v[4]
                        docx_data[f'nd{i}'] = v[5]
                        docx_data[f'hd{i}'] = v[6]
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '拉压扩大土层数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if self.main_window.comboBox_laya_kuoda_cal_method.currentText() == '传统方法':
                    template_path = resource_path('data/锚杆设计计算书——拉压型扩大头抗浮锚杆（传统方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_base):
                        tableWidget_laya_kuoda_base = get_table_all_values(self.main_window.tableWidget_laya_kuoda_base)
                        docx_data['A'] = float(tableWidget_laya_kuoda_base[0][0])
                        docx_data['pk'] = float(tableWidget_laya_kuoda_base[1][0])
                        docx_data['s1'] = float(tableWidget_laya_kuoda_base[2][0])
                        docx_data['s2'] = float(tableWidget_laya_kuoda_base[3][0])
                        docx_data['K'] = float(tableWidget_laya_kuoda_base[4][0])
                        docx_data['fpyk'] = float(tableWidget_laya_kuoda_base[5][0])
                        docx_data['fms'] = float(tableWidget_laya_kuoda_base[6][0])
                        docx_data['h'] = float(tableWidget_laya_kuoda_base[7][0])
                        docx_data['D1'] = float(tableWidget_laya_kuoda_base[8][0])
                        docx_data['D2'] = float(tableWidget_laya_kuoda_base[9][0])
                        docx_data['arf'] = float(tableWidget_laya_kuoda_base[10][0])
                        docx_data['zeta'] = 30.0

                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '拉压扩大传统数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                else:
                    template_path = resource_path('data/锚杆设计计算书——拉压型扩大头抗浮锚杆（优化方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_base_youhua):
                        tableWidget_laya_kuoda_base = get_table_all_values(
                            self.main_window.tableWidget_laya_kuoda_base_youhua)
                        docx_data['A'] = float(tableWidget_laya_kuoda_base[0][0])
                        docx_data['pk'] = float(tableWidget_laya_kuoda_base[1][0])
                        docx_data['s1'] = float(tableWidget_laya_kuoda_base[2][0])
                        docx_data['s2'] = float(tableWidget_laya_kuoda_base[3][0])
                        docx_data['K'] = float(tableWidget_laya_kuoda_base[4][0])
                        docx_data['fpyk'] = float(tableWidget_laya_kuoda_base[5][0])
                        docx_data['fms'] = float(tableWidget_laya_kuoda_base[6][0])
                        docx_data['h_up'] = float(tableWidget_laya_kuoda_base[7][0])
                        docx_data['h_down'] = float(tableWidget_laya_kuoda_base[8][0])
                        docx_data['arf'] = float(tableWidget_laya_kuoda_base[9][0])
                        docx_data['M'] = float(tableWidget_laya_kuoda_base[10][0])
                        docx_data['N'] = float(tableWidget_laya_kuoda_base[11][0])
                        docx_data['zeta'] = 30.0
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '拉压扩大优化数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                if validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_design):
                    tableWidget_laya_kuoda_design = get_table_all_values(self.main_window.tableWidget_laya_kuoda_design)
                    docx_data['sug_count'] = float(tableWidget_laya_kuoda_design[0][0])
                    docx_data['sug_diam'] = float(tableWidget_laya_kuoda_design[1][0])
                    docx_data['sug_D1'] = float(tableWidget_laya_kuoda_design[2][0])
                    docx_data['sug_h'] = float(tableWidget_laya_kuoda_design[3][0])
                    docx_data['sug_D2'] = float(tableWidget_laya_kuoda_design[4][0])
                    docx_data['sug_LD'] = float(tableWidget_laya_kuoda_design[5][0])
                    docx_data['sug_czl'] = float(tableWidget_laya_kuoda_design[6][0])
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '拉压扩大设计数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return

                # if validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_design_user_choice):
                tableWidget_laya_kuoda_design_user_choice = get_table_all_values(
                    self.main_window.tableWidget_laya_kuoda_design_user_choice)
                docx_data['user_count'] = "" if tableWidget_laya_kuoda_design_user_choice[0][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[0][0])
                docx_data['user_diam'] = '' if tableWidget_laya_kuoda_design_user_choice[1][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[1][0])
                docx_data['user_D1'] = '' if tableWidget_laya_kuoda_design_user_choice[2][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[2][0])
                docx_data['user_h'] = '' if tableWidget_laya_kuoda_design_user_choice[3][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[3][0])
                docx_data['user_D2'] = '' if tableWidget_laya_kuoda_design_user_choice[4][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[4][0])
                docx_data['user_LD'] = '' if tableWidget_laya_kuoda_design_user_choice[5][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[5][0])
                docx_data['user_czl'] = '' if tableWidget_laya_kuoda_design_user_choice[6][0] == '' else float(
                    tableWidget_laya_kuoda_design_user_choice[6][0])
                # else:
                #     gener_res['status'] = -1
                #     gener_res['message'] = '拉压扩大用户选择设计数据表格验证失败，请检查数据'
                #     self.update_signal.emit(gener_res)
                #     return
                # 过程数据
                # docx_data['layakuoda_word_As'] = self.main_window.layakuoda_class.word_lD1
                # docx_data['layakuoda_word_lD1'] = self.main_window.layakuoda_class.word_As
                # docx_data['layakuoda_word_Tuk'] = self.main_window.layakuoda_class.word_Tuk
                docx_data["Tuk"] = round_to_two_decimal(self.main_window.layakuoda_class.target_tuk)
                As_jiemian = docx_data.get("user_diam")  # 优先取用户填的参数， 如果用户填的参数为空，则用计算参数
                if As_jiemian == '' or As_jiemian is None:
                    As_jiemian = self.main_window.layakuoda_class.A_s1[1]
                docx_data["As_jiemian"] = round_to_two_decimal((As_jiemian / 2) ** 2 * 3.14159)
                docx_data["As_As_jiemian2"] = round_to_two_decimal(self.main_window.layakuoda_class.A_s1[0])
                docx_data["jiemian_res"] = '通过' if docx_data["As_jiemian"] > docx_data["As_As_jiemian2"] else '未通过'
                LD = docx_data.get("user_LD")
                h = docx_data.get("user_h")
                D1 = docx_data.get("user_D1")
                D2 = docx_data.get("user_D2")

                params = copy.deepcopy(self.main_window.layakuoda_class.__dict__)
                params["design_type"] = params["type"]

                if LD:
                    params["LD"] = LD
                if h:
                    params["h"] = h
                if D1:
                    params["D1"] = D1 * 1000
                if D2:
                    params["D2"] = D2 * 1000
                kk = []
                for k in params:
                    if k not in get_init_parameter_names(AnchorDesign):
                        kk.append(k)
                for k in kk:
                    if k != "design_type":
                        params.pop(k)
                disign = AnchorDesign(**params)
                if LD:
                    disign.LD = LD
                else:
                    LD = docx_data['sug_LD']
                # docx_data["ld_long"] = LD - self.main_window.layakuoda_class.delta_S
                # docx_data["ld_long2"] = self.main_window.layakuoda_class.target_min_ld_without_delta_S
                d = docx_data['user_diam'] if docx_data['user_diam'] != '' and docx_data['user_diam'] is not None else docx_data['sug_diam']
                delta_S = max(0.5, np.tan(np.radians(45) + np.radians(docx_data['zeta']) / 2) * (D2 / 2 - d / 2) / 1000)  # 粘结段长度
                docx_data["deltas"] = round_to_two_decimal(delta_S)
                # pdduanzu
                tmp_h = self.main_window.layakuoda_class.h
                self.main_window.layakuoda_class.h = h
                self.main_window.layakuoda_class.cal_total_tuk()
                # docx_data['pdduanzu'] = round_to_two_decimal(self.main_window.layakuoda_class.PD)
                if self.main_window.copy_obj is None:
                    docx_data['pdduanzu'] = round_to_two_decimal(self.main_window.layakuoda_class.PD)
                else:
                    docx_data['pdduanzu'] = round_to_two_decimal(self.main_window.copy_obj.PD)
                self.main_window.layakuoda_class.h = tmp_h
                docx_data["ld_long"] = round_to_two_decimal(LD - delta_S)
                docx_data["ld_long2"] = round_to_two_decimal(docx_data["Tuk"] / (np.pi * d * docx_data['fms']))
                docx_data["ld_res"] = '通过' if docx_data["ld_long"] >= docx_data["ld_long2"] else '未通过'
                # docx_data["Tukj"] = round_to_two_decimal(disign.cal_total_tuk() + 0.005)
                docx_data["Tukj"] = round_to_two_decimal(docx_data['user_czl'])
                # self.main_window.layakuoda_class.LD = LD_temp
                docx_data["Tukj_res"] = '通过' if docx_data["Tukj"] > docx_data["Tuk"] else '未通过'
                if not validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_cal_all_stable):
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if not self.main_window.layakuoda_class.validation_total_args or len(
                        self.main_window.layakuoda_class.validation_total_args) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算未验算，无法生成计算书'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.layakuoda_class.validation_total(
                    *self.main_window.layakuoda_class.validation_total_args)
                docx_data["wdx_1"] = round_to_two_decimal(res[0])
                docx_data["wdx_2"] = round_to_two_decimal(res[1])
                docx_data["wdx_res"] = '通过' if res[2] else '未通过'

                if '圆形' in self.main_window.comboBox_laya_kuoda_cal_all_maogu.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_cal_maogu):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layakuoda_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.layakuoda_class.strength_validation_circle(
                        **self.main_window.layakuoda_class.strength_validation_circle_kwargs)
                    docx_data["qdc1"] = round_to_two_decimal(res[0])
                    docx_data["qdc2"] = round_to_two_decimal(res[1])
                    docx_data["qdc_res"] = '通过' if res[2] else '未通过'
                    docx_data['qds1'] = '-'
                    docx_data['qds2'] = '-'
                    docx_data['qds_res'] = '-'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_cal_maogu_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layakuoda_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.layakuoda_class.strength_validation_circle(
                        **self.main_window.layakuoda_class.strength_validation_circle_kwargs)
                    docx_data["qds1"] = round_to_two_decimal(res[0])
                    docx_data["qds2"] = round_to_two_decimal(res[1])
                    docx_data["qds_res"] = '通过' if res[2] else '未通过'
                    docx_data['qdc1'] = '-'
                    docx_data['qdc2'] = '-'
                    docx_data['qdc_res'] = '-'

                if '圆形' in self.main_window.comboBox_laya_kuoda_cal_all_maozuo.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_cal_maozuo):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layakuoda_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                    res = self.main_window.layakuoda_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.layakuoda_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_cal_maozuo_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layakuoda_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                    res = self.main_window.layakuoda_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.layakuoda_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'

                if not validate_table_data_thread(self.main_window.tableWidget_laya_kuoda_cal_shouyacz_2):
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                if len(self.main_window.layakuoda_class.validation_shou_ya_chengzai_li_kwargs) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力未验算，请检查数据'
                    self.update_signal.emit(gener_res)
                res = self.main_window.layakuoda_class.validation_shou_ya_chengzai_li(
                    **self.main_window.layakuoda_class.validation_shou_ya_chengzai_li_kwargs)
                docx_data["sy"] = round_to_two_decimal(res[0])
                docx_data['Tdd'] = round_to_two_decimal(res[1])
                docx_data["syres"] = '通过' if res[2] else '未通过'

                output_path = fill_template(template_path, docx_data)
                if output_path:
                    for key, value in docx_data.items():
                        print(f"  {key}: {value}")
            gener_res['status'] = 1
            gener_res['message'] = f'计算书生成成功,路径为: {os.path.normpath(output_path)}'
            self.update_signal.emit(gener_res)  # 发送信号，传递数据
        except Exception as e:
            gener_res['status'] = -1
            gener_res['message'] = f'生成文档失败: {str(e)}'
            self.update_signal.emit(gener_res)


class OutWordThread_layadengzhi(QThread):
    update_signal = Signal(object)

    def __init__(self, main_window=None, algo_class=None):
        super(OutWordThread_layadengzhi, self).__init__()
        self.main_window = main_window
        self.algo_class = algo_class

    def run(self):
        global output_path
        gener_res = {
            "status": "",
            "message": ""
        }
        try:
            docx_data = {}
            # 拉压等直
            if self.main_window.img_index == 1:
                if validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_soil, spec_row_count=1):
                    tableWidget_laya_dengzhi_soil = get_table_all_values(self.main_window.tableWidget_laya_dengzhi_soil)
                    for i, v in enumerate(tableWidget_laya_dengzhi_soil):
                        if i > 5:
                            print('目前只取前6行')
                            break
                        docx_data[f'name{i}'] = v[1]
                        docx_data[f'zd{i}'] = v[2]
                        docx_data[f'nd{i}'] = v[3]
                        docx_data[f'hd{i}'] = v[4]

                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '拉压等直土层数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if self.main_window.comboBox_laya_dengzhi_cal_method.currentText() == '传统方法':
                    template_path = resource_path('data/锚杆设计计算书——拉压型等直径抗浮锚杆（传统方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_base):
                        tableWidget_laya_dengzhi_base = get_table_all_values(
                            self.main_window.tableWidget_laya_dengzhi_base)
                        docx_data['A'] = float(tableWidget_laya_dengzhi_base[0][0])
                        docx_data['pk'] = float(tableWidget_laya_dengzhi_base[1][0])
                        docx_data['s1'] = float(tableWidget_laya_dengzhi_base[2][0])
                        docx_data['s2'] = float(tableWidget_laya_dengzhi_base[3][0])
                        docx_data['K'] = float(tableWidget_laya_dengzhi_base[4][0])
                        docx_data['fpyk'] = float(tableWidget_laya_dengzhi_base[5][0])
                        docx_data['fms'] = float(tableWidget_laya_dengzhi_base[6][0])
                        docx_data['D'] = float(tableWidget_laya_dengzhi_base[7][0])
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '拉压等直传统数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                else:
                    template_path = resource_path('data/锚杆设计计算书——拉压型等直径抗浮锚杆（优化方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_base_youhua):
                        tableWidget_laya_kuoda_base = get_table_all_values(
                            self.main_window.tableWidget_laya_dengzhi_base_youhua)
                        docx_data['A'] = float(tableWidget_laya_kuoda_base[0][0])
                        docx_data['pk'] = float(tableWidget_laya_kuoda_base[1][0])
                        docx_data['s1'] = float(tableWidget_laya_kuoda_base[2][0])
                        docx_data['s2'] = float(tableWidget_laya_kuoda_base[3][0])
                        docx_data['K'] = float(tableWidget_laya_kuoda_base[4][0])
                        docx_data['fpyk'] = float(tableWidget_laya_kuoda_base[5][0])
                        docx_data['fms'] = float(tableWidget_laya_kuoda_base[6][0])
                        docx_data['M'] = float(tableWidget_laya_kuoda_base[7][0])
                        docx_data['N'] = float(tableWidget_laya_kuoda_base[8][0])
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '拉压等直优化数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                if validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_design):
                    tableWidget_laya_dengzhi_design = get_table_all_values(
                        self.main_window.tableWidget_laya_dengzhi_design)
                    docx_data['sug_count'] = float(tableWidget_laya_dengzhi_design[0][0])
                    docx_data['sug_diam'] = float(tableWidget_laya_dengzhi_design[1][0])
                    docx_data['sug_D'] = float(tableWidget_laya_dengzhi_design[2][0])
                    docx_data['sug_lD'] = float(tableWidget_laya_dengzhi_design[3][0])
                    docx_data['sug_lD1'] = float(tableWidget_laya_dengzhi_design[4][0])
                    docx_data['sug_czl'] = float(tableWidget_laya_dengzhi_design[5][0])
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '拉压等直设计数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return

                # if validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_design_user):
                tableWidget_laya_dengzhi_design_user = get_table_all_values(
                    self.main_window.tableWidget_laya_dengzhi_design_user)
                docx_data['user_count'] = '' if tableWidget_laya_dengzhi_design_user[0][0] == '' else float(
                    tableWidget_laya_dengzhi_design_user[0][0])
                docx_data['user_diam'] = '' if tableWidget_laya_dengzhi_design_user[1][0] == '' else float(
                    tableWidget_laya_dengzhi_design_user[1][0])
                docx_data['user_D'] = '' if tableWidget_laya_dengzhi_design_user[2][0] == '' else float(
                    tableWidget_laya_dengzhi_design_user[2][0])
                docx_data['user_lD'] = '' if tableWidget_laya_dengzhi_design_user[3][0] == '' else float(
                    tableWidget_laya_dengzhi_design_user[3][0])
                docx_data['user_lD1'] = '' if tableWidget_laya_dengzhi_design_user[4][0] == '' else float(
                    tableWidget_laya_dengzhi_design_user[4][0])
                docx_data['user_czl'] = '' if tableWidget_laya_dengzhi_design_user[5][0] == '' else float(
                    tableWidget_laya_dengzhi_design_user[5][0])
                # else:
                #     gener_res['status'] = -1
                #     gener_res['message'] = '拉压等直用户选择设计数据表格验证失败，请检查数据'
                #     self.update_signal.emit(gener_res)
                #     return
                # 过程数据
                # todo 获取过程数据
                docx_data["Tuk"] = round_to_two_decimal(self.main_window.layadengzhi_class.target_tuk)
                # docx_data["As_jiemian"] = self.main_window.layadengzhi_class.A_s1[1]
                As_jiemian = docx_data.get("user_diam")  # 优先取用户填的参数， 如果用户填的参数为空，则用计算参数
                if As_jiemian == '' or As_jiemian is None:
                    As_jiemian = self.main_window.layadengzhi_class.A_s1[1]
                docx_data["As_jiemian"] = round_to_two_decimal((As_jiemian / 2) ** 2 * 3.14159)
                docx_data["As_As_jiemian2"] = round_to_two_decimal(self.main_window.layadengzhi_class.A_s1[0])
                docx_data["jiemian_res"] = '通过' if docx_data["As_jiemian"] > docx_data["As_As_jiemian2"] else '未通过'
                # docx_data["ld_long"] = self.main_window.layadengzhi_class.LD - self.main_window.layadengzhi_class.delta_S
                LD = docx_data.get("user_LD")
                h = docx_data.get("user_h")
                D1 = docx_data.get("user_D")
                D2 = docx_data.get("user_D2")
                params = copy.deepcopy(self.main_window.layadengzhi_class.__dict__)
                params["design_type"] = params["type"]

                if LD:
                    params["LD"] = LD
                if h:
                    params["h"] = h
                if D1:
                    params["D1"] = D1 * 1000
                if D2:
                    params["D2"] = D2 * 1000
                kk = []
                for k in params:
                    if k not in get_init_parameter_names(AnchorDesign):
                        kk.append(k)
                for k in kk:
                    if k != "design_type":
                        params.pop(k)

                disign = AnchorDesign(**params)
                nianjieduan_len = self.main_window.layadengzhi_class.target_min_ld_without_delta_S
                if docx_data["user_lD1"]:
                    nianjieduan_len = docx_data["user_lD1"]
                free_len = self.main_window.layadengzhi_class.LD - self.main_window.layadengzhi_class.target_min_ld_without_delta_S
                if docx_data["user_lD"]:
                    free_len = docx_data["user_lD"]
                docx_data["ld_long"] = round_to_two_decimal(nianjieduan_len)
                d = docx_data['user_diam'] if docx_data['user_diam'] != '' and docx_data['user_diam'] is not None else docx_data['sug_diam']
                docx_data["ld_long2"] = round_to_two_decimal(docx_data["Tuk"] / (np.pi * d * docx_data['fms']))
                # docx_data["ld_long2"] = self.main_window.layadengzhi_class.target_min_ld_without_delta_S
                docx_data["ld_res"] = '通过' if docx_data["ld_long"] >= docx_data["ld_long2"] else '未通过'
                # docx_data["Tukj"] = self.main_window.layadengzhi_class.cal_total_tuk()
                disign.LD = nianjieduan_len + free_len
                disign.D1 = docx_data.get("user_D") * 1000
                # disign.LD = self.main_window.layadengzhi_class.LD
                # docx_data["Tukj"] = round_to_two_decimal(disign.cal_total_tuk())# 当两边参数完全一致的时候tuk有点差异，需要排查
                docx_data["Tukj"] = round_to_two_decimal(docx_data['user_czl'])
                self.main_window.layadengzhi_class.cal_total_tuk()
                docx_data["Tukj_res"] = '通过' if docx_data["Tukj"] > docx_data["Tuk"] else '未通过'
                if not validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_cal_all_stable):
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if not self.main_window.layadengzhi_class.validation_total_args or len(
                        self.main_window.layadengzhi_class.validation_total_args) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算未验算，无法生成计算书'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.layadengzhi_class.validation_total(
                    *self.main_window.layadengzhi_class.validation_total_args)
                docx_data["wdx_1"] = round_to_two_decimal(res[0])
                docx_data["wdx_2"] = round_to_two_decimal(res[1])
                docx_data["wdx_res"] = '通过' if res[2] else '未通过'

                if '圆形' in self.main_window.comboBox_laya_dengzhi_cal_all_maogu.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_cal_maogu1):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layadengzhi_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.layadengzhi_class.strength_validation_circle(
                        **self.main_window.layadengzhi_class.strength_validation_circle_kwargs)
                    docx_data["qdc1"] = round_to_two_decimal(res[0])
                    docx_data["qdc2"] = round_to_two_decimal(res[1])
                    docx_data["qdc_res"] = '通过' if res[2] else '未通过'
                    docx_data['qds1'] = '-'
                    docx_data['qds2'] = '-'
                    docx_data['qds_res'] = '-'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_cal_maogu1_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layadengzhi_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.layadengzhi_class.strength_validation_circle(
                        **self.main_window.layadengzhi_class.strength_validation_circle_kwargs)
                    docx_data["qds1"] = round_to_two_decimal(res[0])
                    docx_data["qds2"] = round_to_two_decimal(res[1])
                    docx_data["qds_res"] = '通过' if res[2] else '未通过'
                    docx_data['qdc1'] = '-'
                    docx_data['qdc2'] = '-'
                    docx_data['qdc_res'] = '-'

                if '圆形' in self.main_window.comboBox_laya_dengzhi_cal_all_maozuo.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_cal_maozuo1):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layadengzhi_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.layadengzhi_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.layadengzhi_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_cal_maozuo1_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方型)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.layadengzhi_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方型)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.layadengzhi_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.layadengzhi_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'

                if not validate_table_data_thread(self.main_window.tableWidget_laya_dengzhi_cal_shouyacz):
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if len(self.main_window.layadengzhi_class.validation_shou_ya_chengzai_li_kwargs) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力未验算，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.layadengzhi_class.validation_shou_ya_chengzai_li(
                    **self.main_window.layadengzhi_class.validation_shou_ya_chengzai_li_kwargs)
                docx_data["sy"] = round_to_two_decimal(res[0])
                docx_data['Tdd'] = round_to_two_decimal(res[1])
                docx_data["syres"] = '通过' if res[2] else '未通过'
                output_path = fill_template(template_path, docx_data)
                if output_path:
                    for key, value in docx_data.items():
                        print(f"  {key}: {value}")
            gener_res['status'] = 1
            gener_res['message'] = f'计算书生成成功,路径为: {os.path.normpath(output_path)}'
            self.update_signal.emit(gener_res)  # 发送信号，传递数据
        except Exception as e:
            gener_res['status'] = -1
            gener_res['message'] = f'生成文档失败: {str(e)}'
            self.update_signal.emit(gener_res)


class OutWordThread_yalikuoda(QThread):
    update_signal = Signal(object)

    def __init__(self, main_window=None, algo_class=None):
        super(OutWordThread_yalikuoda, self).__init__()
        self.main_window = main_window
        self.algo_class = algo_class

    def run(self):
        global output_path
        gener_res = {
            "status": "",
            "message": ""
        }
        try:
            docx_data = {}
            # 压力扩大
            if self.main_window.img_index == 2:
                if validate_table_data_thread(self.main_window.tableWidget_yalikuoda_soil, spec_row_count=1):
                    tableWidget_yalikuoda_soil = get_table_all_values(self.main_window.tableWidget_yalikuoda_soil)
                    for i, v in enumerate(tableWidget_yalikuoda_soil):
                        if i > 5:
                            print('目前只取前6行')
                            break
                        docx_data[f'name{i}'] = v[1]
                        docx_data[f'zd{i}'] = v[2]
                        docx_data[f'njl{i}'] = v[3]
                        docx_data[f'nmcj{i}'] = v[4]
                        docx_data[f'nd{i}'] = v[5]
                        docx_data[f'hd{i}'] = v[6]
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '压力扩大土层数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if self.main_window.comboBox_yalikuoda_cal_method.currentText() == '传统方法':
                    template_path = resource_path('data/锚杆设计计算书——压力型扩大头抗浮锚杆（传统方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_yalikuoda_base):
                        tableWidget_yalikuoda_base = get_table_all_values(
                            self.main_window.tableWidget_yalikuoda_base)
                        docx_data['A'] = float(tableWidget_yalikuoda_base[0][0])
                        docx_data['pk'] = float(tableWidget_yalikuoda_base[1][0])
                        docx_data['s1'] = float(tableWidget_yalikuoda_base[2][0])
                        docx_data['s2'] = float(tableWidget_yalikuoda_base[3][0])
                        docx_data['h'] = float(tableWidget_yalikuoda_base[4][0])
                        docx_data['D1'] = float(tableWidget_yalikuoda_base[5][0])
                        docx_data['D2'] = float(tableWidget_yalikuoda_base[6][0])
                        docx_data['K'] = float(tableWidget_yalikuoda_base[7][0])
                        docx_data['fpyk'] = float(tableWidget_yalikuoda_base[8][0])
                        docx_data['arf'] = float(tableWidget_yalikuoda_base[9][0])
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '压力扩大传统数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                else:
                    template_path = resource_path('data/锚杆设计计算书——压力型扩大头抗浮锚杆（优化方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_yalikuoda_base_youhua):
                        tb_data = get_table_all_values(
                            self.main_window.tableWidget_yalikuoda_base_youhua)
                        docx_data['A'] = float(tb_data[0][0])
                        docx_data['pk'] = float(tb_data[1][0])
                        docx_data['s1'] = float(tb_data[2][0])
                        docx_data['s2'] = float(tb_data[3][0])
                        docx_data['h_up'] = float(tb_data[4][0])
                        docx_data['h_down'] = float(tb_data[5][0])
                        docx_data['K'] = float(tb_data[6][0])
                        docx_data['fpyk'] = float(tb_data[7][0])
                        docx_data['arf'] = float(tb_data[8][0])
                        docx_data['M'] = float(tb_data[9][0])
                        docx_data['N'] = float(tb_data[10][0])
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '压力扩大优化数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                if validate_table_data_thread(self.main_window.tableWidget_yalikuoda_design):
                    tb_data = get_table_all_values(
                        self.main_window.tableWidget_yalikuoda_design)
                    docx_data['sug_count'] = float(tb_data[0][0])
                    docx_data['sug_diam'] = float(tb_data[1][0])
                    docx_data['sug_D1'] = float(tb_data[2][0])
                    docx_data['sug_h'] = float(tb_data[3][0])
                    docx_data['sug_D2'] = float(tb_data[4][0])
                    docx_data['sug_LD'] = float(tb_data[5][0])
                    docx_data['sug_czl'] = float(tb_data[6][0])
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '压力扩大设计数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return

                # if validate_table_data_thread(self.main_window.tableWidget_yalikuoda_design_user):
                tb_data = get_table_all_values(
                    self.main_window.tableWidget_yalikuoda_design_user)
                docx_data['user_count'] = '' if tb_data[0][0] == '' else float(tb_data[0][0])
                docx_data['user_diam'] = '' if tb_data[1][0] == '' else float(tb_data[1][0])
                docx_data['user_D1'] = '' if tb_data[2][0] == '' else float(tb_data[2][0])
                docx_data['user_h'] = '' if tb_data[3][0] == '' else float(tb_data[3][0])
                docx_data['user_D2'] = '' if tb_data[4][0] == '' else float(tb_data[4][0])
                docx_data['user_LD'] = '' if tb_data[5][0] == '' else float(tb_data[5][0])
                docx_data['user_czl'] = '' if tb_data[6][0] == '' else float(tb_data[6][0])
                # else:
                #     gener_res['status'] = -1
                #     gener_res['message'] = '压力扩大用户选择设计数据表格验证失败，请检查数据'
                #     self.update_signal.emit(gener_res)
                #     return
                # 过程数据
                # todo 获取过程数据
                docx_data["Tuk"] = round_to_two_decimal(self.main_window.yalikuoda_class.target_tuk)
                # docx_data["As_jiemian"] = self.main_window.yalikuoda_class.A_s1[1]
                As_jiemian = docx_data.get("user_diam")  # 优先取用户填的参数， 如果用户填的参数为空，则用计算参数
                if As_jiemian == '' or As_jiemian is None:
                    As_jiemian = self.main_window.yalikuoda_class.A_s1[1]
                docx_data["As_jiemian"] = round_to_two_decimal((As_jiemian / 2) ** 2 * 3.14159)
                docx_data["As_As_jiemian2"] = round_to_two_decimal(self.main_window.yalikuoda_class.A_s1[0])
                docx_data["jiemian_res"] = '通过' if docx_data["As_jiemian"] > docx_data["As_As_jiemian2"] else '未通过'
                # docx_data["ld_long"] = self.main_window.yalikuoda_class.LD - self.main_window.yalikuoda_class.delta_S
                LD = docx_data.get("user_LD")
                h = docx_data.get("user_h")
                D1 = docx_data.get("user_D1")
                D2 = docx_data.get("user_D2")

                params = copy.deepcopy(self.main_window.yalikuoda_class.__dict__)
                params["design_type"] = params["type"]

                if LD:
                    params["LD"] = LD
                if h:
                    params["h"] = h
                if D1:
                    params["D1"] = D1 * 1000
                if D2:
                    params["D2"] = D2 * 1000
                kk = []
                for k in params:
                    if k not in get_init_parameter_names(AnchorDesign):
                        kk.append(k)
                for k in kk:
                    if k != "design_type":
                        params.pop(k)
                disign = AnchorDesign(**params)

                docx_data["ld_long"] = round_to_two_decimal(disign.LD - self.main_window.yalikuoda_class.delta_S)
                docx_data["ld_long2"] = round_to_two_decimal(self.main_window.yalikuoda_class.target_min_ld_without_delta_S)
                docx_data["ld_res"] = '通过' if docx_data["ld_long"] > docx_data["ld_long2"] else '未通过'
                tmp_h = self.main_window.yalikuoda_class.h
                self.main_window.yalikuoda_class.h = h
                self.main_window.yalikuoda_class.cal_total_tuk()
                # docx_data['pdduanzu'] = round_to_two_decimal(self.main_window.yalikuoda_class.PD)
                if self.main_window.copy_obj is None:
                    docx_data['pdduanzu'] = round_to_two_decimal(self.main_window.yalikuoda_class.PD)
                else:
                    docx_data['pdduanzu'] = round_to_two_decimal(self.main_window.copy_obj.PD)
                self.main_window.yalikuoda_class.h = tmp_h

                # docx_data["Tukj"] = self.main_window.yalikuoda_class.cal_total_tuk()
                disign.LD = docx_data["user_LD"]
                disign.h = docx_data["user_h"]
                disign.D1 = docx_data["user_D1"] * 1000
                disign.D2 = docx_data["user_D2"] * 1000
                # docx_data["Tukj"] = round_to_two_decimal(disign.cal_total_tuk())
                docx_data["Tukj"] = round_to_two_decimal(docx_data['user_czl'])
                docx_data["Tukj_res"] = '通过' if docx_data["Tukj"] > docx_data["Tuk"] else '未通过'
                if not validate_table_data_thread(self.main_window.tableWidget_yalikuoda_cal_all_stable_left):
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if not self.main_window.yalikuoda_class.validation_total_args or len(
                        self.main_window.yalikuoda_class.validation_total_args) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算未验算，无法生成计算书'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.yalikuoda_class.validation_total(
                    *self.main_window.yalikuoda_class.validation_total_args)
                docx_data["wdx_1"] = round_to_two_decimal(res[0])
                docx_data["wdx_2"] = round_to_two_decimal(res[1])
                docx_data["wdx_res"] = '通过' if res[2] else '未通过'

                if '圆形' in self.main_window.comboBox_yalikuoda_cal_all_maogu.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_yalikuoda_cal_maogu):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalikuoda_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalikuoda_class.strength_validation_circle(
                        **self.main_window.yalikuoda_class.strength_validation_circle_kwargs)
                    docx_data["qdc1"] = round_to_two_decimal(res[0])
                    docx_data["qdc2"] = round_to_two_decimal(res[1])
                    docx_data["qdc_res"] = '通过' if res[2] else '未通过'
                    docx_data['qds1'] = '-'
                    docx_data['qds2'] = '-'
                    docx_data['qds_res'] = '-'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_yalikuoda_cal_maogu_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalikuoda_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalikuoda_class.strength_validation_circle(
                        **self.main_window.yalikuoda_class.strength_validation_circle_kwargs)
                    docx_data["qds1"] = round_to_two_decimal(res[0])
                    docx_data["qds2"] = round_to_two_decimal(res[1])
                    docx_data["qds_res"] = '通过' if res[2] else '未通过'
                    docx_data['qdc1'] = '-'
                    docx_data['qdc2'] = '-'
                    docx_data['qdc_res'] = '-'

                if '圆形' in self.main_window.comboBox_yalikuodai_cal_all_maozuo.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_yalikuoda_cal_maozuo):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalikuoda_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalikuoda_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.yalikuoda_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_yalikuoda_cal_maozuo_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalikuoda_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalikuoda_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.yalikuoda_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'

                if not validate_table_data_thread(self.main_window.tableWidget_yali_kuoda_cal_shouyacz):
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if len(self.main_window.yalikuoda_class.validation_shou_ya_chengzai_li_kwargs) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力未验算，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.yalikuoda_class.validation_shou_ya_chengzai_li(
                    **self.main_window.yalikuoda_class.validation_shou_ya_chengzai_li_kwargs)
                docx_data["sy"] = round_to_two_decimal(res[0])
                docx_data['Tdd'] = round_to_two_decimal(res[1])
                docx_data["syres"] = '通过' if res[2] else '未通过'

                if not validate_table_data_thread(self.main_window.tableWidget_yalikuoda_cal_all_stable_right):
                    gener_res['status'] = -1
                    gener_res['message'] = '局部受压验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if not self.main_window.yalikuoda_class.validation_jubu_shouya_kwargs or len(
                        self.main_window.yalikuoda_class.validation_jubu_shouya_kwargs) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '局部受压验算未验算，无法生成计算书'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.yalikuoda_class.validation_jubu_shouya(
                    **self.main_window.yalikuoda_class.validation_jubu_shouya_kwargs)
                docx_data["jbsy"] = round_to_two_decimal(res[0])
                docx_data["jbsyres"] = '通过' if res[1] else '未通过'
                output_path = fill_template(template_path, docx_data)
                if output_path:
                    for key, value in docx_data.items():
                        print(f"  {key}: {value}")
            gener_res['status'] = 1
            gener_res['message'] = f'计算书生成成功,路径为: {os.path.normpath(output_path)}'
            self.update_signal.emit(gener_res)  # 发送信号，传递数据
        except Exception as e:
            gener_res['status'] = -1
            gener_res['message'] = f'生成文档失败: {str(e)}'
            self.update_signal.emit(gener_res)


class OutWordThread_yalidengzhi(QThread):
    update_signal = Signal(object)

    def __init__(self, main_window=None, algo_class=None):
        super(OutWordThread_yalidengzhi, self).__init__()
        self.main_window = main_window
        self.algo_class = algo_class

    def run(self):
        global output_path
        gener_res = {
            "status": "",
            "message": ""
        }
        try:
            docx_data = {}
            # 压力等直
            if self.main_window.img_index == 3:
                if validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_soil, spec_row_count=1):
                    tableWidget_yalikuoda_soil = get_table_all_values(self.main_window.tableWidget_yalidengzhi_soil)
                    for i, v in enumerate(tableWidget_yalikuoda_soil):
                        if i > 5:
                            print('目前只取前6行')
                            break
                        docx_data[f'name{i}'] = v[1]
                        docx_data[f'zd{i}'] = v[2]
                        docx_data[f'nd{i}'] = v[3]
                        docx_data[f'hd{i}'] = v[4]
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '压力等直土层数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if self.main_window.comboBox_yalidengzhi_cal_method.currentText() == '传统方法':
                    template_path = resource_path('data/锚杆设计计算书——压力型等直径抗浮锚杆（传统方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_base):
                        tableWidget_yalikuoda_base = get_table_all_values(
                            self.main_window.tableWidget_yalidengzhi_base)
                        docx_data['A'] = float(tableWidget_yalikuoda_base[0][0])
                        docx_data['pk'] = float(tableWidget_yalikuoda_base[1][0])
                        docx_data['s1'] = float(tableWidget_yalikuoda_base[2][0])
                        docx_data['s2'] = float(tableWidget_yalikuoda_base[3][0])
                        docx_data['K'] = float(tableWidget_yalikuoda_base[4][0])
                        docx_data['fpyk'] = float(tableWidget_yalikuoda_base[5][0])
                        docx_data['D'] = float(tableWidget_yalikuoda_base[6][0])
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '压力等直传统数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                else:
                    template_path = resource_path('data/锚杆设计计算书——压力型等直径抗浮锚杆（优化方法）.docx')
                    if validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_base_youhua):
                        tb_data = get_table_all_values(
                            self.main_window.tableWidget_yalidengzhi_base_youhua)
                        docx_data['A'] = float(tb_data[0][0])
                        docx_data['pk'] = float(tb_data[1][0])
                        docx_data['s1'] = float(tb_data[2][0])
                        docx_data['s2'] = float(tb_data[3][0])
                        docx_data['K'] = float(tb_data[4][0])
                        docx_data['fpyk'] = float(tb_data[5][0])
                        docx_data['M'] = float(tb_data[6][0])
                        docx_data['N'] = float(tb_data[7][0])
                    else:
                        gener_res['status'] = -1
                        gener_res['message'] = '压力等直优化数据表格验证失败，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                if validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_design):
                    tb_data = get_table_all_values(
                        self.main_window.tableWidget_yalidengzhi_design)
                    docx_data['sug_count'] = float(tb_data[0][0])
                    docx_data['sug_diam'] = float(tb_data[1][0])
                    docx_data['sug_D'] = float(tb_data[2][0])
                    docx_data['sug_LD'] = float(tb_data[3][0])
                    docx_data['sug_czl'] = float(tb_data[4][0])
                    # docx_data['sug_lD1'] = float(tb_data[4][0])
                else:
                    gener_res['status'] = -1
                    gener_res['message'] = '压力等直设计数据表格验证失败，请检查数据'
                    self.update_signal.emit(gener_res)
                    return

                # if validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_design_user):
                tb_data = get_table_all_values(
                    self.main_window.tableWidget_yalidengzhi_design_user)
                docx_data['user_count'] = '' if tb_data[0][0] == '' else float(tb_data[0][0])
                docx_data['user_diam'] = '' if tb_data[1][0] == '' else float(tb_data[1][0])
                docx_data['user_D'] = '' if tb_data[2][0] == '' else float(tb_data[2][0])
                docx_data['user_LD'] = '' if tb_data[3][0] == '' else float(tb_data[3][0])
                docx_data['user_czl'] = '' if tb_data[4][0] == '' else float(tb_data[4][0])
                # docx_data['user_lD1'] = '' if tb_data[4][0] == '' else float(tb_data[4][0])
                # else:
                #     gener_res['status'] = -1
                #     gener_res['message'] = '压力等直用户选择设计数据表格验证失败，请检查数据'
                #     self.update_signal.emit(gener_res)
                #     return
                # 过程数据
                # todo  获取过程数据
                docx_data["Tuk"] = round_to_two_decimal(self.main_window.yalidengzhi_class.target_tuk)
                # docx_data["As_jiemian"] = self.main_window.yalidengzhi_class.A_s1[1]
                As_jiemian = docx_data.get("user_diam")  # 优先取用户填的参数， 如果用户填的参数为空，则用计算参数
                if As_jiemian == '' or As_jiemian is None:
                    As_jiemian = self.main_window.yalidengzhi_class.A_s1[1]
                docx_data["As_jiemian"] = round_to_two_decimal((As_jiemian / 2) ** 2 * 3.14159)
                docx_data["As_As_jiemian2"] = round_to_two_decimal(self.main_window.yalidengzhi_class.A_s1[0])
                docx_data["jiemian_res"] = '通过' if docx_data["As_jiemian"] > docx_data["As_As_jiemian2"] else '未通过'
                # docx_data["ld_long"] = self.main_window.yalidengzhi_class.LD - self.main_window.yalidengzhi_class.delta_S
                LD = docx_data.get("user_LD")
                h = docx_data.get("user_h")
                D1 = docx_data.get("user_D1")
                D2 = docx_data.get("user_D2")

                params = copy.deepcopy(self.main_window.yalidengzhi_class.__dict__)
                params["design_type"] = params["type"]

                if LD:
                    params["LD"] = LD
                if h:
                    params["h"] = h
                if D1:
                    params["D1"] = D1 * 1000
                if D2:
                    params["D2"] = D2 * 1000
                kk = []
                for k in params:
                    if k not in get_init_parameter_names(AnchorDesign):
                        kk.append(k)
                for k in kk:
                    if k != "design_type":
                        params.pop(k)
                disign = AnchorDesign(**params)
                disign.LD = docx_data["user_LD"]
                disign.D1 = docx_data['user_D']*1000

                docx_data["ld_long"] = round_to_two_decimal(disign.LD - self.main_window.yalidengzhi_class.delta_S)
                docx_data["ld_long2"] = round_to_two_decimal(self.main_window.yalidengzhi_class.target_min_ld_without_delta_S)
                docx_data["ld_res"] = '通过' if docx_data["ld_long"] > docx_data["ld_long2"] else '未通过'
                # docx_data["Tukj"] = self.main_window.yalidengzhi_class.cal_total_tuk()
                # docx_data["Tukj"] = round_to_two_decimal(disign.cal_total_tuk())
                docx_data["Tukj"] = round_to_two_decimal(docx_data['user_czl'])
                docx_data["Tukj_res"] = '通过' if docx_data["Tukj"] > docx_data["Tuk"] else '未通过'
                if not validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_cal_all_stable_left):
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if not self.main_window.yalidengzhi_class.validation_total_args or len(
                        self.main_window.yalidengzhi_class.validation_total_args) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '整体稳定性验算未验算，无法生成计算书'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.yalidengzhi_class.validation_total(
                    *self.main_window.yalidengzhi_class.validation_total_args)
                docx_data["wdx_1"] = round_to_two_decimal(res[0])
                docx_data["wdx_2"] = round_to_two_decimal(res[1])
                docx_data["wdx_res"] = '通过' if res[2] else '未通过'

                if '圆形' in self.main_window.comboBox_yalidengzhi_cal_all_maogu.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_cal_maogu):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalidengzhi_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalidengzhi_class.strength_validation_circle(
                        **self.main_window.yalidengzhi_class.strength_validation_circle_kwargs)
                    docx_data["qdc1"] = round_to_two_decimal(res[0])
                    docx_data["qdc2"] = round_to_two_decimal(res[1])
                    docx_data["qdc_res"] = '通过' if res[2] else '未通过'
                    docx_data['qds1'] = '-'
                    docx_data['qds2'] = '-'
                    docx_data['qds_res'] = '-'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_cal_maogu_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalidengzhi_class.strength_validation_circle_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚固板强度(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalidengzhi_class.strength_validation_circle(
                        **self.main_window.yalidengzhi_class.strength_validation_circle_kwargs)
                    docx_data["qds1"] = round_to_two_decimal(res[0])
                    docx_data["qds2"] = round_to_two_decimal(res[1])
                    docx_data["qds_res"] = '通过' if res[2] else '未通过'
                    docx_data['qdc1'] = '-'
                    docx_data['qdc2'] = '-'
                    docx_data['qdc_res'] = '-'

                if '圆形' in self.main_window.comboBox_yalidengzhi_cal_all_maozuo.currentText():
                    if not validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_cal_maozuo):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalidengzhi_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(圆形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalidengzhi_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.yalidengzhi_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'
                else:
                    if not validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_cal_maozuo_square):
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方形)验算参数未设置，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    if len(self.main_window.yalidengzhi_class.validation_chong_qie_cheng_zai_li_kwargs) == 0:
                        gener_res['status'] = -1
                        gener_res['message'] = '锚座节点冲切承载力(方形)未验算，请检查数据'
                        self.update_signal.emit(gener_res)
                        return
                    res = self.main_window.yalidengzhi_class.validation_chong_qie_cheng_zai_li(
                        **self.main_window.yalidengzhi_class.validation_chong_qie_cheng_zai_li_kwargs)
                    docx_data["cq1"] = round_to_two_decimal(res[0])
                    docx_data["cq2"] = round_to_two_decimal(res[1])
                    docx_data["cqres"] = '通过' if res[2] else '未通过'

                if not validate_table_data_thread(self.main_window.tableWidget_yali_dengzhi_cal_shouyacz):
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if len(self.main_window.yalidengzhi_class.validation_shou_ya_chengzai_li_kwargs) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '锚座节点受压承载力未验算，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.yalidengzhi_class.validation_shou_ya_chengzai_li(
                    **self.main_window.yalidengzhi_class.validation_shou_ya_chengzai_li_kwargs)
                docx_data["sy"] = round_to_two_decimal(res[0])
                docx_data['Tdd'] = round_to_two_decimal(res[1])
                docx_data["syres"] = '通过' if res[2] else '未通过'

                if not validate_table_data_thread(self.main_window.tableWidget_yalidengzhi_cal_all_stable_right):
                    gener_res['status'] = -1
                    gener_res['message'] = '局部受压验算参数未设置，请检查数据'
                    self.update_signal.emit(gener_res)
                    return
                if not self.main_window.yalidengzhi_class.validation_jubu_shouya_kwargs or len(
                        self.main_window.yalidengzhi_class.validation_jubu_shouya_kwargs) == 0:
                    gener_res['status'] = -1
                    gener_res['message'] = '局部受压验算未验算，无法生成计算书'
                    self.update_signal.emit(gener_res)
                    return
                res = self.main_window.yalidengzhi_class.validation_jubu_shouya(
                    **self.main_window.yalidengzhi_class.validation_jubu_shouya_kwargs)
                docx_data["jbsy"] = round_to_two_decimal(res[0])
                docx_data["jbsyres"] = '通过' if res[1] else '未通过'
                output_path = fill_template(template_path, docx_data)
                if output_path:
                    for key, value in docx_data.items():
                        print(f"  {key}: {value}")
            gener_res['status'] = 1
            gener_res['message'] = f'文档生成成功,路径为: {os.path.normpath(output_path)}'
            self.update_signal.emit(gener_res)  # 发送信号，传递数据
        except Exception as e:
            gener_res['status'] = -1
            gener_res['message'] = f'生成文档失败: {str(e)}'
            self.update_signal.emit(gener_res)


def tab_widget_switch(tabwidget, index):
    """
    界面上tbawidget切换
    :param tabwidget:
    :param index:
    :return:
    """
    try:
        tabwidget.setCurrentIndex(index)
    except Exception as e:
        print(f"切换标签页失败: {str(e)}")


def set_table_height(table):
    table.resizeRowsToContents()
    table_height = table.horizontalHeader().height()  # 表头高度
    for row in range(table.rowCount()):
        table_height += table.rowHeight(row)  # 每行高度
    extra_height = 3 * table.frameWidth() + 10
    table.setFixedHeight(table_height + extra_height)


def show_hide_layout(layout_name, show=True):
    """
    显示或隐藏布局中的所有控件
    :return:
    """
    main_layout = layout_name.layout()

    # 遍历布局中的所有项
    for i in range(main_layout.count()):
        item = main_layout.itemAt(i)

        # 检查项是否包含widget
        if item.widget():
            widget = item.widget()
            # 切换widget的可见性
            if show:
                widget.show()
            else:
                widget.hide()


def validate_table_data(table, msg='错误提示', is_show_box=True):
    """
    验证表格数据
    :param table:
    :return:
    """
    for d in range(table.rowCount()):
        for c in range(table.columnCount()):
            item = table.item(d, c)
            if item is None:
                if is_show_box:
                    QMessageBox.critical(table, "错误", msg)
                return False
            if item.text() == "":
                if is_show_box:
                    QMessageBox.critical(table, "错误", msg)
                return False
    return True


def validate_table_data_thread(table, spec_row_count=0):
    """
    验证表格数据，在子线程中
    :param table:
    :return:
    """
    for d in range(table.rowCount() if spec_row_count == 0 else spec_row_count):
        for c in range(table.columnCount()):
            item = table.item(d, c)
            if item is None:
                return False
            if item.text() == "":
                return False
    return True


def text_edit_set_text_color(text_edit, text, result_text, success=False):
    cursor = text_edit.textCursor()
    cursor.setCharFormat(QTextCharFormat())
    cursor.insertText(text)
    color_format = QTextCharFormat()
    if success:
        color_format.setForeground(QColor(0, 180, 0))
    else:
        color_format.setForeground(QColor(255, 0, 0))  # 红色
    cursor.insertText(result_text + '\n', color_format)
    text_edit.moveCursor(QTextCursor.End)


def formart_date():
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

def sync_cell(target_table, target_row, target_col, content):
    """
    同步内容到目标表格的指定单元格

    参数:
        target_table: 目标表格对象(QTableWidget)
        target_row: 目标行索引
        target_col: 目标列索引
        content: 要同步的内容
    """
    # 边界检查
    if (target_row < 0 or target_row >= target_table.rowCount() or
            target_col < 0 or target_col >= target_table.columnCount()):
        QMessageBox.warning(target_table, "错误", "目标单元格超出表格范围")
        return

    # 获取或创建目标单元格
    target_item = target_table.item(target_row, target_col)
    if not target_item:
        target_item = QTableWidgetItem()
        target_table.setItem(target_row, target_col, target_item)

    # 同步内容（禁用信号防止循环触发）
    target_table.blockSignals(True)
    target_item.setText(str(content))
    target_table.blockSignals(False)


class LoadingDialog(QDialog):
    """加载对话框"""

    def __init__(self, parent=None, msg="正在生成，请稍候..."):
        super().__init__(parent)
        self.setWindowTitle("请稍候")
        self.setFixedSize(200, 100)
        self.setWindowModality(Qt.ApplicationModal)  # 模态对话框，阻止用户操作其他窗口

        layout = QVBoxLayout()
        self.label = QLabel(msg)
        self.label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.label)

        self.setLayout(layout)


class AboutDialog(QDialog):
    """关于信息对话框"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("关于")
        self.setFixedSize(300, 200)  # 设置固定大小
        self.init_ui()

    def init_ui(self):
        # 创建布局
        main_layout = QVBoxLayout()
        main_layout.setAlignment(Qt.AlignCenter)
        main_layout.setSpacing(15)  # 设置控件间距

        # 软件名称
        title_label = QLabel("软件信息")
        title_font = QFont()
        title_font.setPointSize(16)
        title_font.setBold(True)
        title_label.setFont(title_font)
        title_label.setAlignment(Qt.AlignCenter)

        # 版本信息
        version_label = QLabel("版本: v1.0.0")
        version_label.setAlignment(Qt.AlignCenter)

        # 版权信息
        copyright_label = QLabel("© 2025 中冶成都勘察研究总院有限公司. 保留所有权利.")
        copyright_label.setAlignment(Qt.AlignCenter)
        copyright_label.setStyleSheet("color: #666666;font-size:16px")
        copyright_label.setWordWrap(True)

        # 描述信息
        desc_label = QLabel("高强度预应力锚杆设计软件V1.0")
        desc_label.setAlignment(Qt.AlignCenter)
        # desc_label.setWordWrap(True)  # 自动换行
        desc_label.setStyleSheet("margin: 10px 0;")

        # 添加控件到布局
        main_layout.addWidget(title_label)
        main_layout.addWidget(version_label)
        main_layout.addWidget(desc_label)
        main_layout.addWidget(copyright_label)

        # 设置布局
        self.setLayout(main_layout)


# 自定义带渐变背景的组件
class GradientImageWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 保留你的原始设置
        self.setObjectName(u"widget_launch")
        self.setEnabled(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)

        # 加载图片
        self.bg_pixmap = QPixmap(":/imgs/launch.png")

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # 绘制原始图片
        painter.drawPixmap(self.rect(), self.bg_pixmap.scaled(
            self.size(),
            Qt.KeepAspectRatioByExpanding,
            Qt.SmoothTransformation
        ))

        # 创建白色渐变遮罩（关键修改：用白色替代黑色）
        gradient = QLinearGradient(0, 0, 0, self.height())

        # 上方：白蒙蒙效果（白色带透明度）
        gradient.setColorAt(0.0, QColor(255, 255, 255, 230))
        # 中间过渡点：逐渐变清晰
        gradient.setColorAt(0.5, QColor(255, 255, 255, 15))
        # 下方：完全清晰（白色完全透明）
        gradient.setColorAt(1.0, QColor(255, 255, 255, 0))

        # 应用渐变遮罩
        painter.setBrush(QBrush(gradient))
        painter.setPen(Qt.NoPen)
        painter.drawRect(self.rect())


class ButtonDelegate(QStyledItemDelegate):
    # 定义一个信号，用于在按钮被点击时传递该单元格的模型索引
    buttonClicked = Signal(QModelIndex)

    def __init__(self, parent=None):
        super().__init__(parent)
        self._button_rect = None  # 用于存储当前绘制按钮的矩形区域

    def paint(self, painter, option, index):
        """
        重写paint方法，绘制单元格内容和按钮。
        """
        # 首先调用父类方法绘制原始的单元格背景和内容（文本等）
        super().paint(painter, option, index)

        # 定义按钮的尺寸和位置（位于单元格右侧）
        button_margin = 2  # 按钮边距
        button_width = 20  # 按钮宽度
        # 计算按钮的矩形区域
        button_rect = option.rect.adjusted(option.rect.width() - button_width - button_margin,
                                          button_margin,
                                          -button_margin,
                                          -button_margin)
        self._button_rect = button_rect  # 存储当前按钮区域，供editorEvent判断

        # 配置按钮的样式选项
        button_option = QStyleOptionButton()
        button_option.rect = button_rect
        button_option.text = ">"  # 按钮上显示的文字，也可以用图标
        button_option.state = QStyle.State_Enabled  # 按钮状态设为可用

        # 如果鼠标正在当前单元格区域，为按钮添加悬停效果
        if option.state & QStyle.State_MouseOver:
            button_option.state |= QStyle.State_MouseOver

        # 使用应用程序的样式来绘制按钮
        QApplication.style().drawControl(QStyle.CE_PushButton, button_option, painter)

    def createEditor(self, parent, option, index):
        """
        创建编辑器（一个QLineEdit），并为其设置输入验证。
        """
        # 创建一个QLineEdit作为编辑器
        editor = QLineEdit(parent)
        # 设置输入验证：只允许数字、小数点，且小数点后最多两位
        regex = QRegularExpression(r"^(\d*\.?\d{0,2}|\d+\.?)$")  # 允许数字、小数点后最多两位、空值
        validator = QRegularExpressionValidator(regex)
        editor.setValidator(validator)
        return editor

    def setEditorData(self, editor, index):
        """
        从模型获取数据，并设置到编辑器中。
        """
        # 获取模型中当前索引的数据（字符串形式）
        value = index.model().data(index, Qt.EditRole)
        # 将数据设置到编辑器中
        editor.setText(value)

    def setModelData(self, editor, model, index):
        """
        将编辑器中的数据保存回模型。
        """
        # 获取编辑器中的文本
        value = editor.text()
        # 将文本设置回模型中
        model.setData(index, value, Qt.EditRole)

    def editorEvent(self, event, model, option, index):
        """
        处理编辑器事件，判断点击是否发生在按钮上。
        """
        # 只处理鼠标释放事件
        if event.type() == event.MouseButtonRelease:
            # 检查点击位置是否在之前存储的按钮矩形区域内
            if self._button_rect is not None and self._button_rect.contains(event.pos()):
                # 如果在按钮上点击，发射buttonClicked信号，传递当前单元格的索引
                self.buttonClicked.emit(index)
                return True  # 返回True表示已处理该事件，阻止进一步的编辑操作
        # 如果不是点击按钮，则调用父类方法，允许正常的单元格编辑
        return super().editorEvent(event, model, option, index)

class ImageDialog(QDialog):
    """显示背景图片的子窗口"""

    def __init__(self, parent=None, title='钢筋力学特性表'):
        super(ImageDialog, self).__init__(parent)
        self.setWindowTitle(title)
        self.resize(853, 355)
        # 设置最小尺寸
        self.setMinimumSize(512, 213)
        # 设置最大尺寸
        self.setMaximumSize(2270, 710)

        # 设置布局
        layout = QVBoxLayout()

        # 创建标签用于显示图片
        self.image_label = QLabel()
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.setScaledContents(True)  # 允许图片缩放
        layout.addWidget(self.image_label)

        self.setLayout(layout)

    def set_image(self, image_path):
        """设置要显示的图片"""
        pixmap = QPixmap(image_path)
        if not pixmap.isNull():
            self.image_label.setPixmap(pixmap)
        else:
            self.image_label.setText("图片加载失败")